import logging
import yaml
import os
import copy
import time
import concurrent.futures
from pathlib import Path
from typing import Dict, Any, Optional, Union, List, Tuple, Set
from concurrent.futures import ThreadPoolExecutor, as_completed

# 假设这些导入是正确且必要的
from .telemetry_loader import TelemetryLoader
from .openRCA_loader import TelecomDataLoader, MarketDataLoader, BankDataLoader
from .base_loader import BaseDataLoader, AnomalyRecord
from source.detect.detection_manager import DetectionManager  # 假设路径正确
from source.localize.graph.CompositeCausalGraph import CompositeCausalGraph
from source.localize.circa.runner import CircaRunner

logger = logging.getLogger(__name__)



class LoaderFactory:
    """数据加载器工厂类，用于创建不同类型的数据加载器实例。"""

    @staticmethod
    def create_loader(
        data_source_config: Dict[str, Any],
        output_dir: Union[str, Path],
        data_processing_config: Dict[str, Any],
    ) -> Optional[BaseDataLoader]:
        """
        根据数据源配置创建数据加载器实例。

        参数:
            data_source_config (Dict[str, Any]): 单个数据源的配置字典。
            output_dir (Union[str, Path]): 该数据源的输出子目录路径。
            data_processing_config (Dict[str, Any]): 全局的数据处理配置。

        返回:
            Optional[BaseDataLoader]: 数据加载器实例，如果创建失败则返回 None。
        """
        base_dir = data_source_config.get("base_dir", "")
        # 从数据源配置中获取类型，例如 'market', 'telecom', 'bank'
        data_source_type = data_source_config.get("type", "").lower()
        # output_path 是此数据源的专用输出路径，例如 .../output_base_dir/run_exp_id/market/
        output_path = (
            Path(output_dir) if not isinstance(output_dir, Path) else output_dir
        )

        # 如果配置文件中未明确指定数据源类型，则尝试从 base_dir 推断
        if not data_source_type and base_dir:
            dir_name = Path(base_dir).name.lower()
            if "telemetry" in dir_name or "otel" in dir_name:  # OpenTelemetry 数据集
                data_source_type = "telemetry"
            elif "telecom" in dir_name:  # 电信数据集
                data_source_type = "telecom"
            elif "market" in dir_name:  # 商城数据集
                data_source_type = "market"
            elif "bank" in dir_name:  # 银行数据集 (新增的推断规则)
                data_source_type = "bank"
            else:
                logger.error(
                    f"无法从目录名 '{dir_name}' 推断数据源类型。请在配置文件中明确指定 'type'。"
                )
                return None
            logger.info(
                f"根据目录名 '{dir_name}' 推断数据源类型为: '{data_source_type}'"
            )
        elif not data_source_type:
            logger.error("数据源配置中缺少 'type' 且无法从 'base_dir' 推断类型。")
            return None

        # 从全局数据处理配置中获取采样、平滑和缓存相关的参数
        sampling_cfg = data_processing_config.get("sampling", {})
        smoothing_cfg = data_processing_config.get("smoothing", {})
        cache_cfg = data_processing_config.get("cache", {})
        # 全局工作线程数，各个加载器可以按需使用
        num_workers_global = data_processing_config.get("num_workers", 1)

        # 采样率的确定：优先使用数据源自身的配置，若无，则使用全局配置
        # 注意：具体的加载器（如 BankDataLoader）可能会有自己的采样逻辑或忽略此参数
        ds_sampling_cfg = data_source_config.get("sampling", {})
        final_sampling_interval = ds_sampling_cfg.get(
            "interval", sampling_cfg.get("interval", 60)
        )
        final_sampling_enabled = ds_sampling_cfg.get(
            "enabled", sampling_cfg.get("enabled", True)
        )
        sampling_rate_str = (
            f"{final_sampling_interval}s" if final_sampling_enabled else None
        )

        loader_common_params = {
            "base_data_path": base_dir,
            "output_dir": str(output_path),  # 单个数据源的输出目录
            "sampling_rate": sampling_rate_str,  # 最终确定的采样率字符串
            "smooth_method": smoothing_cfg.get("method", "linear"),
            "smooth_limit": smoothing_cfg.get("limit", 5),
            "num_workers": num_workers_global,  # 全局工作线程数
            "use_cache": cache_cfg.get("enabled", True),
            "record_file_name": data_source_config.get(
                "record_file_name", "record.csv"
            ),  # 允许数据源配置不同的记录文件名
        }

        # 根据推断或配置的 data_source_type 创建相应的加载器实例
        if data_source_type == "telemetry":
            logger.info(
                f"创建 OpenTelemetry 数据加载器，来源: {base_dir or '配置定义的数据源'}"
            )
            return TelemetryLoader(**loader_common_params)
        elif data_source_type == "telecom":
            logger.info(
                f"创建 Telecom 数据加载器，来源: {base_dir or '配置定义的数据源'}"
            )
            return TelecomDataLoader(**loader_common_params)
        elif data_source_type == "market":
            logger.info(
                f"创建 Market 数据加载器，来源: {base_dir or '配置定义的数据源'}"
            )
            return MarketDataLoader(**loader_common_params)
        elif data_source_type == "bank":  # <-- 新增: 处理银行数据集类型
            logger.info(f"创建 Bank 数据加载器，来源: {base_dir or '配置定义的数据源'}")
            return BankDataLoader(**loader_common_params)
        else:
            logger.error(f"不支持的数据源类型: '{data_source_type}'")
            return None


